//
//  railwaysController.m
//  ElektroM
//
//  Created by Michael on 09.10.09.
//  Copyright 2009 Artgruppe inc. All rights reserved.
//

#import "railwaysController.h"
#import "Constants.h"
#import "chooseStation.h"
#import "MainViewController.h"
#import "showInfoWindow.h"
#include "MyMath.h"

@implementation railwaysController

@synthesize databaseName;
@synthesize image;
@synthesize scrollView;
@synthesize name;
@synthesize canvas;
@synthesize timeTableController;
@synthesize stationSelectController;
@synthesize navController;

@synthesize btnStationStart, btnStationEnd, bottomToolbar;

// labels:
@synthesize lblTimeStation1ToMoscow, lblTimeStation1FromMoscow, lblTimeStation2ToMoscow, lblTimeStation2FromMoscow;

#pragma mark -
#pragma mark Initalization
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {	
		_nFirstFoundStation=-1;
		_nSecondFoundStation=-1;		
		timeTableController=nil;
		_bReformDrawBuffer=false;		
		_db=nil;
		_aiParents=nil;
		_aiWeights=nil;
    }
	
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    _nLastSecondStation=-1;
    _nLastFirstStation=-1;
	
	[scrollView setBackgroundColor:[UIColor whiteColor]];
	[scrollView setCanCancelContentTouches:NO];
	scrollView.clipsToBounds = YES;	// default is NO, we want to restrict drawing within our scrollview
	scrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack;
	[self setTitle:name];

	[self loadAllNeededStuff];

	// add our custom image button as the nav bar's custom right view
	UIBarButtonItem *timeButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"clock.png"]
								  style:UIBarButtonItemStyleBordered target:self action:@selector(showTimes)];
	self.navigationItem.rightBarButtonItem = timeButton;
	[timeButton release];
	
}

-(void) setQuer:(bool) bQuer
{
	_bShowQuer=bQuer;
}

-(void) loadAllNeededStuff
{
    //printf("My name is %s and I want to load my resources!\n", [databaseName UTF8String]);
    _bUnneededStuffWasReleased=false;
    if(self.image==nil)
    {
		self.image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:
								 [databaseName stringByAppendingString:@".png"]]];
		[scrollView addSubview: self.image];
		[scrollView addSubview:image];
		[scrollView setContentSize:CGSizeMake(image.frame.size.width, image.frame.size.height)];
		[scrollView setScrollEnabled:YES];	
    }
	 	
    // update canvas (drawing stuff):
    canvas.scroll=scrollView;
    [canvas initization];
    
    if(_db==nil){
		_db=[dataBase alloc];
		_db.namePrefix=databaseName;
		NSString* strDB=[databaseName stringByAppendingString:@"Railways.sqlite"];
		_db.databaseName=strDB;
		//[strDB release];
    }
    [_db initialization];

	//printf("Start using db;\n");
    _aiCentersX = [_db readCentersAsNSArray];
    _aiCentersY = [_db getCentersYAsNSArray];
   
	//create all needed data for that then and calculate it:   
	_aiNext = [_db readStationStructureAsNSArrayAndLoadAlsoNames: true];
	_diNodes = [_db getNodesOfStationsAsNSArray];
	// get read names pointer:
	_aiStationNames = [_db getStationNamesAsNSArray];
	
	//printf("Loaded next elements count: %d\n", [_aiNext count]);

	[self applyCyclonToWholeStructure:0];
	// then you do not need _aiNext and _diNodes any more, release them:
						      // no we do need them:
	[_aiNext release];
	_aiNext = nil;
	[_diNodes release];
	_diNodes = nil;
	// and we do not need the weight in current release:
	//[_aiWeights release];
	_aiWeights = nil;
	
	/*
	// (I will not use that stuff right now);
	// now I need to load all sightseeing to station ids, 
	// to now, if our user chose one
    _aiSStationIds=[_db getSightseeingAllStationIdsOnly];
    //[_aiSStationIds retain];
    _nAmountSightSeeingStIds=[_db getAmountOfSightSeeingStationIds];
	 */
	
    _nFirstFoundStation=[master storageGetSelectedStations:1 FromController:databaseName];
    if(_nFirstFoundStation<0 || _nFirstFoundStation>[_aiStationNames count])
	_nFirstFoundStation=-1;
    if(_nFirstFoundStation!=-1 && _nFirstFoundStation<[_aiStationNames count]){		
	//[self recalculateGraph];
    }

    _nSecondFoundStation=[master storageGetSelectedStations:2 FromController:databaseName];
    //printf("Second found station: %d\n", _nSecondFoundStation);
    // correction if we've got damaged value from the file:
    if(_nSecondFoundStation<0 || _nSecondFoundStation>[_aiStationNames count])
	_nSecondFoundStation=-1;
	
	//printf("All resources were loaded!\n");
  
    //[_aiParents retain];
    [self updateInterface];   
}

-(void) releaseAllStuff
{
    //printf("My Name is: %s and I want to release my resources!\n", [databaseName UTF8String]);
    _bUnneededStuffWasReleased=true;
    [_aiStationNames release];	
    _aiStationNames=nil;
    [_aiCentersX release];
    _aiCentersX=nil;

    [_aiCentersY release];
    _aiCentersY=nil;	
	/*
    if(_aiSStationIds!=nil)
	[_aiSStationIds release];
    _aiSStationIds=nil;
    */	
	
	if(_aiParents !=nil){		
		//printf("Retain count: %d\n", [_aiParents retainCount]);
		//while([_aiParents retainCount]>1)
			[_aiParents release];
	}
    _aiParents = nil;
    [canvas utilization];
    /// and at last release image from the canvas:
    [self.image removeFromSuperview];
    //[self.image release];
    self.image=nil;		 
    if(timeTableController != nil)
    {
	//[timeTableController releaseUnneededData];
	//[timeTableController release];
	self.timeTableController=nil;
    }
    if(showTimeWindow != nil)
    {
	[showTimeWindow release];
	showTimeWindow=nil;
    }
	if(_db!=nil)
	{
		_db.namePrefix=nil;
		_db.databaseName=nil;
		[_db release];
		_db=nil;
	}
}

-(bool) unneededStuffWasReleased
{
    return _bUnneededStuffWasReleased;
}

#pragma mark -
#pragma mark Touches
// touching controlling for station selection:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {	
	
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint ptWhere = [touch locationInView:touch.view];				
    _bAreWeInScrollMode=false;

    if([touch tapCount]==1){
	_bNeedToCalculateGraph=true;
	[NSTimer scheduledTimerWithTimeInterval: 0.1
					 target:self selector:@selector(performGraphCalc) 
				       userInfo:nil repeats: NO];	

	_ptWhereLast=ptWhere;
    }
    else
	_bNeedToCalculateGraph=false;
}

-(void) performGraphCalc
{
    if(_bNeedToCalculateGraph)
		[self findStationInPoint: _ptWhereLast];
}

// update our view as we do the scroll process:
- (void)scrollViewDidScroll:(UIScrollView *)scrollViewChanged
{
	_bAreWeInScrollMode=true;
}

#pragma mark -
#pragma mark C++ Stuff (now Objective-C too)
// now I'll port it only to Objective-C
-(void)findStationInPoint:(CGPoint) ptCur
{
    [self disableUserInteraction];
	// an array to sort out found stations with minimum distance to 
	// our point:
	int* found_mins;
	int nFoundCount=0;
	int getN=10;
	for(int i=0; i<[_aiCentersX count]; i++)
	{		
	    // here we should translate our coordinates into 
	    // the coordinate system of the image...
	    double dDist=sqrt(sqr([[_aiCentersX objectAtIndex: i] intValue] - ptCur.x + 2*kOffsetX+
					image.frame.origin.x)+
					sqr([[_aiCentersY objectAtIndex: i] intValue] - ptCur.y + 3*kOffsetY+
					image.frame.origin.y));


	    if(fabs(dDist) < kMinDistanceToPoint)
	    {
			// memory allocation:
			if(nFoundCount==0)
				found_mins=(int*)malloc(sizeof(int)*getN);
			if(nFoundCount>getN)
			{
				getN*=2;
				int *anTmp=(int*)malloc(sizeof(int)*getN);
				for(int j=0; j<nFoundCount; j++)
					anTmp[j]=found_mins[j];
				
				free(found_mins);
				found_mins=anTmp;
			}
			// add found node to the array:
			found_mins[nFoundCount++]=i;
	    }
	}
	int min=Infinity;
	int j=0;
	int min_ind=-1;
	for(int i=0; i<nFoundCount; i++)
	{	    
	    j=found_mins[i];
	    double dDist=sqrt(sqr([[_aiCentersX objectAtIndex: i] intValue]-ptCur.x+2*kOffsetX)+
			      sqr([[_aiCentersY objectAtIndex: i] intValue]-ptCur.y+3*kOffsetY));
	    if( dDist < min)
	    {
			min=dDist;
			min_ind=j;
	    }
	}		
	free(found_mins);	
	// now show the found station:	
	if(min_ind!=-1){
	    //printf("Found a station! %d\n", min_ind);
		// for testing purposes show the station:
		if(_nFirstFoundStation==-1 || abs(_nFirstFoundStation-min_ind)<3)
			_nFirstFoundStation=min_ind;
		else if(abs(_nFirstFoundStation-min_ind)>3 || abs(_nSecondFoundStation-min_ind)<3)
			_nSecondFoundStation=min_ind;			
		//NSLog(@"%s", _aStations[nFoundId].sName);
		if(_nFirstFoundStation>=0){			
			// recalculate the nodes:
			//[self recalculateGraph];				
		}		
		_nLastNumber=min_ind;
		[self updateInterface];		
	}	 
	else
	    [self enableUserInteraction];
}
#pragma mark -
#pragma mark Drawing
-(void) drawSelection
{
    if(_bReformDrawBuffer){
	//canvas.backgroundColor = [UIColor colorWithRed:0.16f green:0.45f blue:0.87f alpha:1.0f];
	canvas.backgroundColor = [UIColor colorWithRed:0.0f green:0.38f blue:0.19f alpha:1.0f];
	if(_nFirstFoundStation!=-1)
	{
	    UIColor *color=[[UIColor alloc] initWithRed:1.0 green:0.0 blue:0.0 alpha: 0.5];
	    [self drawNodeNormalStation:NO Color:color StationIndex:_nFirstFoundStation];									
	    [color release];		/// if movement was in the play:		
	    //[bottomToolBar setHidden:YES];
	}
	if(_nSecondFoundStation!=-1)
	{	
	    //printf("Loading second station: %d\n", _nSecondFoundStation);
	    //printf("Adding second found station!\n");
	    UIColor *color=[[UIColor alloc] initWithRed:1.0 green:0.0 blue:0.0 alpha: 0.5];
	    [self drawNodeNormalStation:NO Color:color StationIndex:_nSecondFoundStation];									
	    [color release];		
	}
	UIColor *colorDest=[[UIColor alloc] initWithRed:1.0 green:1.0 blue:1.0 alpha: 1.0f];

	int nFirst=_nSecondFoundStation<_nFirstFoundStation?_nSecondFoundStation:_nFirstFoundStation;
	int nSecond=_nSecondFoundStation<_nFirstFoundStation?_nFirstFoundStation:_nSecondFoundStation;


	if(_nSecondFoundStation!=-1 && _nFirstFoundStation!=_nSecondFoundStation && _nFirstFoundStation!=-1)
	{
	    NSMutableArray* aiParentOfFirst=[NSMutableArray arrayWithCapacity: [_aiParents count]];
	    int nCurNode=nFirst;
	    while(nCurNode!=0)
	    {
		[aiParentOfFirst addObject: 
		    [NSNumber numberWithInt: nCurNode]];
		nCurNode=[[_aiParents objectAtIndex: nCurNode] intValue];
	    }
	    // then try make up something from that info:
	    int nLastStation;
	    int parent;

	    nLastStation=nSecond;
	    [self drawLineWithColor:colorDest StationIndex: nSecond];
	    bool bFoundNode=false;
		parent=[[_aiParents objectAtIndex: nSecond] intValue];
		
	    do{	
		if((abs([[_aiCentersX objectAtIndex: parent] intValue] - 
			[[_aiCentersX objectAtIndex: nLastStation] intValue]))>5)
		{	
			int upper=[[_aiCentersY objectAtIndex:nLastStation] intValue]>
				[[_aiCentersY objectAtIndex: parent] intValue]?nLastStation:parent;
			int below=(upper==parent)?nLastStation:parent;
			
		    [self drawLineWithColor:colorDest StationIndex: nLastStation];
			if(!_bShowQuer){
				if(!bFoundNode){
					[self drawLineWithColor:colorDest withPoint: 
					 CGPointMake([[_aiCentersX objectAtIndex:upper] intValue]+kOffsetX,
								 [[_aiCentersY objectAtIndex:upper] intValue]+kOffsetY-23)];
					
					[self drawLineWithColor:colorDest withPoint: 			
					 CGPointMake([[_aiCentersX objectAtIndex: below] intValue]+kOffsetX,
								 [[_aiCentersY objectAtIndex: below] intValue]+kOffsetY+23)];		
				}
				else
				{
					[self drawLineWithColor:colorDest withPoint: 			
					 CGPointMake([[_aiCentersX objectAtIndex: below] intValue]+kOffsetX,
								 [[_aiCentersY objectAtIndex: below] intValue]+kOffsetY+23)];
					
					[self drawLineWithColor:colorDest withPoint: 
					 CGPointMake([[_aiCentersX objectAtIndex:upper] intValue]+kOffsetX,
								 [[_aiCentersY objectAtIndex:upper] intValue]+kOffsetY-23)];
				}
			
			}
		    [self drawLineWithColor:colorDest StationIndex: parent];		 
		}
		// try to find out, if there is a value in the first
		// history path 
		if(!bFoundNode)
		if([aiParentOfFirst containsObject: [NSNumber numberWithInt: parent]])
		    bFoundNode=true;// we've found it!

		if(!bFoundNode)
		{
		    nLastStation=parent;
		    parent = [[_aiParents objectAtIndex: parent] intValue];
		}
		else
		{
		    nLastStation = parent;
		    int nIndex=[aiParentOfFirst indexOfObject: 
			[NSNumber numberWithInt: parent]];
		    if(nIndex>=1)
			parent = [[aiParentOfFirst objectAtIndex: nIndex-1] intValue];
		    else
			parent=nFirst;
		}

	    }
	    while(parent!=nFirst);
	    [self drawLineWithColor:colorDest StationIndex: nFirst];
	    aiParentOfFirst=nil;
	}
	[colorDest release];
    }
}

// draws a station from the centers db
-(void)drawNodeNormalStation:(bool)bOrdinal Color:(UIColor*)color StationIndex:(int)index
{	
	if(_bReformDrawBuffer){
		DrawItem* item=[DrawItem alloc];
		
		item.type = TYPE_ANIMATION;
		item.animationDuration = 2.0f;
		item.center=CGPointMake([[_aiCentersX objectAtIndex: index] intValue]+kOffsetX,
			[[_aiCentersY objectAtIndex: index] intValue]+kOffsetY);	

		if(index==_nFirstFoundStation)
		    item.animPictures = [NSArray arrayWithObjects: 
								 [UIImage imageNamed:@"endImage.png"], 
								 [UIImage imageNamed:@"endImage1.png"], 
								 [UIImage imageNamed:@"endImage2.png"], 
								 nil];
		else
		    item.animPictures = [NSArray arrayWithObjects: 
								 [UIImage imageNamed:@"startImage.png"], 
								 [UIImage imageNamed:@"startImage1.png"], 
								 [UIImage imageNamed:@"startImage2.png"], 
								 nil];
		item.color=color;	
		[canvas addObjectToDraw:item];
		
	}
}


-(void)drawLineWithColor:(UIColor*)color withPoint:(CGPoint)pt
{
	DrawItem* item=[DrawItem alloc];
	
	item.rad=0;
	item.type=TYPE_LINE;
	item.center=pt;
	item.color=color;
	[canvas addObjectToDraw:item];		
}

-(void)drawLineWithColor:(UIColor*)color StationIndex:(int)index
{	
	//printf("Added line %d (%d, %d)\n", index, _anCenters[index].nX, _anCenters[index].nY);
	DrawItem* item=[DrawItem alloc];
	
	item.rad=0;
	item.type=TYPE_LINE;
	
	item.center = CGPointMake(
		[[_aiCentersX objectAtIndex: index] intValue]+kOffsetX,
			[[_aiCentersY objectAtIndex: index] intValue]+kOffsetY);	

	item.color=color;
	[canvas addObjectToDraw:item];		
}

#pragma mark -
#pragma mark delegates
-(IBAction) showTimeTable:(id)button
{	
	int nFoundId=0;
	if(((UIButton*)button).tag==1)
		nFoundId=_nFirstFoundStation;
	else
		nFoundId=_nSecondFoundStation;

	
	if(nFoundId==-1)
	{
		//show alert and get out of here:
		UIAlertView *styleAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"SelectStation", @"")
																 message:NSLocalizedString(@"SelectStationExplain", @"") 
																delegate:self 
															   cancelButtonTitle:NSLocalizedString(@"Cancel", @"")
															 otherButtonTitles:nil];				
		[styleAlert show];
		[styleAlert release];		
		
		return;
	}
	
		
	//NSString* statName=_aStations[centersOfRailways[nFoundId].nId-1].sName;
	if(timeTableController==nil)
	{
		timeTableView *timeTable = 
		[[timeTableView alloc] initWithNibName:@"timeTableView" 
											   bundle:nil];
		self.timeTableController = timeTable;
		[timeTable release];
	}	
	timeTableController._nStationId = nFoundId;
	timeTableController._sDataBaseName = self.databaseName;		
	
	timeTableController.strTitle = [_aiStationNames objectAtIndex: nFoundId];
	    //strNames[centersOfRailways[nFoundId].nId-1];
	timeTableController.tabBarController=self.tabBarController;	
	timeTableController._direction = 0;
	
	[timeTableController updateData];
	
	_bLoadSubControllers=true;
	
	[self hideToolbarWithAnimationAndInfo:0];	
	//[self.navigationController pushViewController:timeTableController animated:YES];	
}

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
	if (self.stationSelectController == nil)
        self.stationSelectController = [[[chooseStation alloc] initWithNibName:
					   NSStringFromClass([chooseStation class]) bundle:nil] autorelease];		

	[stationSelectController setStationsInfoAsNSArray: _aiStationNames 
											withCount: [_aiStationNames count] 
				    		andRailwaysController:self];

	_bLoadSubControllers=true;
	_nTextFieldStationSelection=textField.tag;
	
	[self.navigationController presentModalViewController:self.stationSelectController animated:YES];	
	
	return FALSE;
}

-(IBAction) showTimes
{    
	if(_nFirstFoundStation!=-1 && _nSecondFoundStation!=-1)
	{		
		_bLoadSubControllers=true;
		if (showTimeWindow == nil)
			showTimeWindow =  [[showTime alloc] initWithNibName:@"showTime" bundle:nil];		

		NSString* str=[NSString stringWithFormat:@"%@ - %@", 
							   [_aiStationNames objectAtIndex: _nFirstFoundStation],
							   [_aiStationNames objectAtIndex: _nSecondFoundStation]];		


		//printf("Label Name:%s\n", [str UTF8String]);
		
		[showTimeWindow.lblStationNames setText:str];

		showTimeWindow.namePrefix=databaseName;
		showTimeWindow.startStation=_nFirstFoundStation;
		showTimeWindow.endStation=_nSecondFoundStation;

		str=[NSString stringWithFormat:@"%@ - %@", 
			[_aiStationNames objectAtIndex: _nSecondFoundStation],
			[_aiStationNames objectAtIndex: _nFirstFoundStation]];

		[showTimeWindow.lblStationNamesRev setText:str];
		
		if(_nFirstFoundStation<=_nSecondFoundStation)
		{
			showTimeWindow.lblStationTimes.text=self.lblTimeStation1FromMoscow.text;
			showTimeWindow.lblStationTimesRev.text=self.lblTimeStation2ToMoscow.text;
		}
		else{
			showTimeWindow.lblStationTimes.text=self.lblTimeStation2ToMoscow.text;
			showTimeWindow.lblStationTimesRev.text=self.lblTimeStation1FromMoscow.text;
		}
		
		[self.navigationController presentModalViewController:showTimeWindow animated:YES];
	}
	else
	{		
		//show alert and get out of here:
		UIAlertView *styleAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"SelectStation", @"")
						 message:NSLocalizedString(@"SelectStationExplain", @"") 
							delegate:self 
						   	cancelButtonTitle:NSLocalizedString(@"Ok", @"")
							otherButtonTitles:nil];	
		
		[styleAlert show];
		[styleAlert release];		
	}
	
}

-(void) showInfoOnAnyOfStations
{
    // now try to find, if there are some 
    // records in the sightseeing db:
    
   if(_nAmountSightSeeingStIds>0)
   if([_aiSStationIds containsObject:[NSNumber numberWithInt: _nSecondFoundStation]] || 
      [_aiSStationIds containsObject:[NSNumber numberWithInt: _nFirstFoundStation]])      
   {
       if(_bSightsWereShown && !_bHideInfoPanelWasForced
	       && [_aiSStationIds containsObject: [NSNumber numberWithInt: _nLastNumber]])
       {
	   //printf("User wants hide the panel!\n");
	   _bHideInfoPanelWasForced=true;
	   // user wants to hide that awful panel, oblidge him:
	   if(!showSightseeings.hidden)
	       [self hideToolbarInfoWithAnimationAndInfo:0];
	   else
	       [self showToolbarInfoWithAnimationAndInfo:0];

	   return;
       }
       else if(_bHideInfoPanelWasForced && _bSightsWereShown
	       && [_aiSStationIds containsObject:[NSNumber numberWithInt: _nLastNumber]])
	   return;
       _bSightsWereShown=true;
       //printf("Panel wake up!\n");
       //showSightseeings.tag=number;
       if(showSightseeings.hidden)
	   [self showToolbarInfoWithAnimationAndInfo:0];		
       return;
   }	
   // there are no stations with any data attached to them,
   // hide the panel and tell the system to show the info panel 
   // next time:
   //printf("We haven't found the elements, panel go back!\n");
   _bSightsWereShown=false;
   _bHideInfoPanelWasForced=false;

   [self hideToolbarInfoWithAnimationAndInfo:0];	
}

-(IBAction) showInfoWindow
{
	if(infoWindow!=nil)
	{
		[infoWindow release];
		infoWindow = nil;
	}
	//showInfoWindow* info=
	infoWindow=[[showInfoWindow alloc] initWithNibName:@"showInfoWindow" bundle:nil];	
	//[info release];
	
	
	[infoWindow setStationInfo:_nFirstFoundStation andSecond:_nSecondFoundStation];
	[self.navigationController pushViewController:infoWindow animated:YES];
}

#pragma mark -
#pragma mark Structure
-(void) applyCyclonToWholeStructure:(int)Start
{
	//printf("Cyclon Starting..\n");
    if(_aiNext!=nil && _diNodes!=nil)
    {
	// first initialize our _aiParents and _aiWeights
	// structures;
	if(_aiParents==nil || _aiWeights==nil)
	{
	    _aiParents = [NSMutableArray arrayWithCapacity: [_aiNext count]];
	    _aiWeights = [NSMutableArray arrayWithCapacity: [_aiNext count]];

	    for(int i=0; i<[_aiNext count]; i++)
	    {
		[_aiParents addObject: [NSNumber numberWithInt: -1]];
		[_aiWeights addObject: [NSNumber numberWithInt: Infinity]];
	    }
	    // for the starting point of calculation:
	    [_aiWeights replaceObjectAtIndex: Start withObject: [NSNumber numberWithInt: 0]];
	    	    
	}
	int nCurNode=0;

	int aWhere[kWhereCount];
	int nWhereCur=0;

	for(;;)
	{
	    // check out, if we have 
	    // nodes;
	    NSNumber* node=[_diNodes objectForKey: [NSNumber numberWithInt: nCurNode]];
	    if(node!=nil)
	    {
		// first relax it:
		[self relaxNode: [node intValue] withNode: nCurNode withWeight:1];
		// then add it to the queue:
		aWhere[nWhereCur++]=[node intValue];
	    }
	    // then go to the next number:
	    if([[_aiNext objectAtIndex: nCurNode] intValue] !=-1)
	    {
		[self relaxNode: [[_aiNext objectAtIndex: nCurNode] intValue] 
		    withNode: nCurNode withWeight:1];
		// add it to the queue too:
		aWhere[nWhereCur++]=[[_aiNext objectAtIndex: nCurNode] intValue];
	    }
	    
	    // now we have to look through the queue to go to the next node:
	    if(nWhereCur>0)
		nCurNode = aWhere[--nWhereCur];
	    else
		break;
	}
	
	//[_aiParents retain];
	//[_aiWeights release];
    }
    else 
	printf("_aiNext or _diNodes wasn't initialized!\n"); 

    [_aiParents retain];
    if([_aiWeights retainCount]>1)	   
		[_aiWeights release];
	//printf("End of cyclon!\n");
}

-(void) relaxNode:(int)nRelaxing withNode:(int)nFrom withWeight:(int)nWeight
{
    if([[_aiWeights objectAtIndex: nRelaxing] intValue] > 
	    [[_aiWeights objectAtIndex: nFrom] intValue] + nWeight)
    {
		NSNumber* newweight=[NSNumber numberWithInt: [[_aiWeights objectAtIndex: nFrom] intValue] + nWeight];
		[_aiWeights replaceObjectAtIndex: nRelaxing withObject: newweight];
		
		NSNumber* parent=[NSNumber numberWithInt: nFrom];
		[_aiParents replaceObjectAtIndex: nRelaxing withObject: parent];		
    }
}

-(void) recalculateGraph
{
    //printf("Recalculating graph...\n");
    [self applyCyclonToWholeStructure: _nFirstFoundStation];
    [_aiParents retain];
	//printf("End of Recalculating graph...\n");
}

#pragma mark User Interaction 
-(void) disableUserInteraction
{
    self.navigationController.navigationBar.userInteractionEnabled = NO;
    scrollView.userInteractionEnabled = NO;
    bottomToolbar.userInteractionEnabled = NO;
}

-(void) enableUserInteraction
{
    self.navigationController.navigationBar.userInteractionEnabled = YES;
    scrollView.userInteractionEnabled = YES;
    bottomToolbar.userInteractionEnabled = YES;
}

#pragma mark Update Interface 
-(void) setSelection:(int)selected
{
	if(_nTextFieldStationSelection==1){
		_nFirstFoundStation=selected;
		//_nStationsToCentersMap[selected*MaximumPointsForNode];
		//printf("Found index: %d\n", _nFirstFoundStation);
	}
	else{
		_nSecondFoundStation=selected;//_nStationsToCentersMap[selected*MaximumPointsForNode];	
		//printf("Found Sec index: %d\n", _nSecondFoundStation);	
	}	
	// recalculate the nodes (we've changed nodes structure - while using Modal dialog):
	//[self recalculateGraph];
	[self updateInterface];
}

-(void) updateInterface
{
    //printf("Updating user interface!\n");
    _bReformDrawBuffer=true;
    // delete old points:	
    [canvas haveToDestroyBuffer];
    // and form the new ones:	
    [self drawSelection];	
    [canvas DrawThemAll];
    //[canvas setNeedsDisplayInRect: [canvas getRectToUpdate]];
    _bReformDrawBuffer=false;

	//printf("After drawing operations; Updating elements\n");
    if(_nFirstFoundStation!=-1)
    {
	btnStationStart.text=[_aiStationNames objectAtIndex: _nFirstFoundStation];
    }
    else
	btnStationStart.text=@"X"; 

    if(_nSecondFoundStation!=-1)
    {
	btnStationEnd.text=[_aiStationNames objectAtIndex: _nSecondFoundStation];
    }
    else
	btnStationEnd.text=@"X"; 

	//printf("Load resources from storage!\n");
    // tell the master about changes in station selection:
    [master storageSetSelectedStations:1 TheStationValue:_nFirstFoundStation FromController:databaseName];		
    [master storageSetSelectedStations:2 TheStationValue:_nSecondFoundStation FromController:databaseName];
     //[self updateFromDBStationsInfo];
    //[self showInfoOnAnyOfStations];
    [self enableUserInteraction];
	
	/*
	[NSTimer scheduledTimerWithTimeInterval: 1.0f
	target:self selector:@selector(acquireInfoAboutFirstStation) userInfo:nil repeats: NO];	
	 */
	//printf("End of update interface\n");
}

-(void) acquireInfoAboutFirstStation
{
    if(!_bLoadSubControllers)
    {
	// if we need to update that field:
	if(_nLastFirstStation!=_nFirstFoundStation){
	    if(_db==nil){
		_db=[dataBase alloc];	
		_db.namePrefix=databaseName;
		_db.databaseName=[databaseName stringByAppendingString:@"Railways.sqlite"];
	    }
	    [_db initialization];

	    if(_nFirstFoundStation!=-1){		
		NSString* aTimeToMoscow=[_db readTimeTableByCenterIdShort:_nFirstFoundStation withDirection:1];
		NSString* aTimeFromMoscow=[_db readTimeTableByCenterIdShort:_nFirstFoundStation withDirection:0];

		[lblTimeStation1ToMoscow setText:aTimeToMoscow];
		[lblTimeStation1FromMoscow setText:aTimeFromMoscow];
		[aTimeToMoscow release];
		[aTimeFromMoscow release];
	    }
	    else
	    {
		[lblTimeStation1ToMoscow setText:@"??.??"];
		[lblTimeStation1FromMoscow setText:@"??.??"];
	    }
	}
	_nLastFirstStation=_nFirstFoundStation;

	// second station info:
	[NSTimer scheduledTimerWithTimeInterval: 1.0 
		target:self selector:@selector(acquireInfoAboutSecondStation) userInfo:nil repeats: NO];
    }
}

-(void) acquireInfoAboutSecondStation
{
    if(!_bLoadSubControllers)
    {
	if(_nLastSecondStation!=_nSecondFoundStation){
	    [_db initialization];

	    if(_nSecondFoundStation!=-1){		
		NSString* aTimeToMoscow=[_db readTimeTableByCenterIdShort:_nSecondFoundStation withDirection:1];
		NSString* aTimeFromMoscow=[_db readTimeTableByCenterIdShort:_nSecondFoundStation withDirection:0];

		[lblTimeStation2ToMoscow setText:aTimeToMoscow];
		[lblTimeStation2FromMoscow setText:aTimeFromMoscow];

		[aTimeToMoscow release];
		[aTimeFromMoscow release];
	    }
	    else
	    {
		[lblTimeStation2ToMoscow setText:@"??.??"];
		[lblTimeStation2FromMoscow setText:@"??.??"];	
	    }
	}
	_nLastSecondStation=_nSecondFoundStation;
    }

}

// getting small info about train arrival times
-(void) updateFromDBStationsInfo
{		
	dataBase* db=[dataBase alloc];	
	db.namePrefix=databaseName;
	db.databaseName=[databaseName stringByAppendingString:@"Railways.sqlite"];
	[db initialization];
	
	if(_nFirstFoundStation!=-1){		
		NSString* aTimeToMoscow=[db readTimeTableByCenterIdShort:_nFirstFoundStation withDirection:1];
	 	NSString* aTimeFromMoscow=[db readTimeTableByCenterIdShort:_nFirstFoundStation withDirection:0];
		
		[lblTimeStation1ToMoscow setText:aTimeToMoscow];
		[lblTimeStation1FromMoscow setText:aTimeFromMoscow];
	}
	else
	{
		[lblTimeStation1ToMoscow setText:@"??.??"];
		[lblTimeStation1FromMoscow setText:@"??.??"];
	}
	
	if(_nSecondFoundStation!=-1){		
		NSString* aTimeToMoscow=[db readTimeTableByCenterIdShort:_nSecondFoundStation withDirection:1];
	 	NSString* aTimeFromMoscow=[db readTimeTableByCenterIdShort:_nSecondFoundStation withDirection:0];
		
		[lblTimeStation2ToMoscow setText:aTimeToMoscow];
		[lblTimeStation2FromMoscow setText:aTimeFromMoscow];
	}
	else
	{
		[lblTimeStation2ToMoscow setText:@"??.??"];
		[lblTimeStation2FromMoscow setText:@"??.??"];	
	}
}

-(IBAction) resetStation:(id)button
{
	if(((UIButton*)button).tag==1){
		_nFirstFoundStation=-1;
	}
	else{
		_nSecondFoundStation=-1;	
	}
	// make our selection come true
	[self updateInterface];
}
/*
// TODO: try to make that regime;
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
#pragma mark -
#pragma mark Recycle
- (void)didReceiveMemoryWarning {
	//printf("Memory warning!\n");
	// Releases the view if it doesn't have a superview.
    //[self releaseAllStuff];	
    // try to release all unneeded elements
    [(MainViewController*)master releaseAllUnneededElements: self.databaseName];
    [super didReceiveMemoryWarning];
	//printf("Memory warning!!! on railways window!\n");	
	// Release any cached data, images, etc that aren't in use
}

- (void)viewDidUnload {
	//printf("railways: viewDidUnload\n");
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
	//printf("Railways View will unload!\n");	
	//[self releaseAllStuff];
	if(_aiParents!=nil)
		[self releaseAllStuff];
	
	self.image=nil;	
	self.scrollView=nil;	
	//self.databaseName=nil;	
	self.bottomToolbar=nil;	
	self.btnStationStart=nil;	
	self.btnStationEnd=nil;
}

- (void)dealloc {
	/*
	if(image!=nil)
	    [image release];
	if(scrollView!=nil)
	    [scrollView release];
	if(databaseName!=nil)
	    [databaseName release];
	if(bottomToolbar!=nil)
	    [bottomToolbar release];
	if(btnStationStart!=nil)
	    [btnStationStart release];	
	if(btnStationEnd!=nil)
	    [btnStationEnd release];
	 */
	[super dealloc];
}

#pragma mark -
#pragma mark TabBar dancing
- (void)viewWillAppear:(BOOL)animated{ 	
    	if(_aiStationNames==nil || self.image==nil || _bUnneededStuffWasReleased)
		[self loadAllNeededStuff];
	
	if(timeTableController!=nil)
		[timeTableController releaseUnneededData];
	   

	if(self.tabBarController!=nil && !_bWasResized && !_bLoadSubControllers){
		// another try:	
		self.tabBarController.tabBar.hidden=YES;		
		//printf("Showing bottom toolbar! (1)\n");
		// remove needed for us toolbar from overlapped window
		[bottomToolbar removeFromSuperview];		
		bottomToolbar.frame=CGRectMake(0, 404, 360, 76);
		
		// ... and make it stay on top
		// I need add here some animation
		[self.tabBarController.view.superview addSubview:bottomToolbar];		
		self.navController.view.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
		//TODO: return here animation, please:
		//[self showToolbarWithAnimationAndInfo:kShowJustToolbar];
		_bWasResized=true;
		//printf("End of Showing bottom toolbar! (1)\n");
	}
	
	if(_bLoadSubControllers)
	{
		//printf("Showing bottom toolbar!\n");
	    scrollView.frame = CGRectMake(0, 0, 327, kScrollViewHeight);
		//bottomToolbar.frame=CGRectMake(0, 404, 360, 76);
	    [self showToolbarWithAnimationAndInfo:kShowJustToolbar];
		//[bottomToolbar setHidden:NO];
		//printf("End of Showing bottom toolbar!\n");	
	}	
	// end of that scheme
	_bLoadSubControllers=false;
}

- (void)viewWillDisappear:(BOOL)animated{
    // the scheme to hide bottom tab bar (from Apple)
    if(self.tabBarController!=nil && _bWasResized && !_bLoadSubControllers){
		self.tabBarController.tabBar.hidden=NO;		
		[bottomToolbar removeFromSuperview];
		[self.view addSubview:bottomToolbar];
		//self.tabBarController.tabBar.hidden=NO;
		[self showToolbarWithAnimationAndInfo:kShowJustToolbar];
		_bWasResized=false;
	}	
	if(_bLoadSubControllers)
	{	
		//printf("Time to show our bar");		
		[self hideToolbarWithAnimationAndInfo:kHideToolbarOnly];
		//[bottomToolbar setHidden:YES];
	}
	// end of that scheme
	
	//printf("Writting data to file.\n");	
	// write all info we need to disk
	[master writeStorage];
}

#pragma mark -
#pragma mark Animation
-(void) hideToolbarWithAnimationAndInfo:(int)nInfo
{
	self.scrollView.userInteractionEnabled = NO;

	_dyAnimation=1.0f;
	if(nInfo==0)
		[NSTimer scheduledTimerWithTimeInterval:kTimeAnimation 
										 target:self selector:@selector(fadeOutToolbar:) userInfo:nil repeats:YES];
	else if(nInfo==1)
		[NSTimer scheduledTimerWithTimeInterval:kTimeAnimation 
										 target:self selector:@selector(fadeOutToolbarSimple:) userInfo:nil repeats:YES];
}

-(void) showToolbarWithAnimationAndInfo:(int)nInfo
{
	self.scrollView.userInteractionEnabled = NO;
	
	_dyAnimation=0.5f;
	CGRect old=bottomToolbar.frame;
	bottomToolbar.frame=CGRectMake(old.origin.x, kScreenHeight, old.size.width, old.size.height);
	bottomToolbar.hidden=NO;
	if(nInfo==0)
		[NSTimer scheduledTimerWithTimeInterval:kTimeAnimation target:self 
									   selector:@selector(fadeInToolbar:) userInfo:nil repeats:YES];
	
}

- (void)fadeOutToolbarSimple:(NSTimer*)theTimer
{
	CGRect old=bottomToolbar.frame;
	_dyAnimation*=1.25;
	bottomToolbar.frame=CGRectMake(old.origin.x, old.origin.y+_dyAnimation, 
								   old.size.width, old.size.height);
	if(old.origin.y>kScreenHeight || _bAreWeInScrollMode){
		[theTimer invalidate];
		[bottomToolbar setHidden:YES];
		self.scrollView.userInteractionEnabled = YES;
	}
	
}

- (void)fadeOutToolbar:(NSTimer*)theTimer
{
	CGRect old=bottomToolbar.frame;
	_dyAnimation*=1.25;
	bottomToolbar.frame=CGRectMake(old.origin.x, old.origin.y+_dyAnimation, 
								   old.size.width, old.size.height);
	if(old.origin.y>kScreenHeight || _bAreWeInScrollMode){
		[theTimer invalidate];
		[self.navigationController pushViewController:timeTableController animated:YES];		
		self.scrollView.userInteractionEnabled = YES;
	}
}

- (void)fadeInToolbar:(NSTimer*)theTimer
{
	
	CGRect old=bottomToolbar.frame;
	_dyAnimation*=1.25;
	bottomToolbar.frame=CGRectMake(old.origin.x, old.origin.y-_dyAnimation, 
								   old.size.width, old.size.height);
	//printf("Fade in toolbar! %.0f\n", old.origin.y-_dyAnimation);
	if(old.origin.y<kStationsToolbarCy+10 || _bAreWeInScrollMode){
		[theTimer invalidate];
		bottomToolbar.frame=CGRectMake(old.origin.x, kStationsToolbarCy, 
									   old.size.width, old.size.height);
		self.scrollView.userInteractionEnabled = YES;
	}
	
}

#pragma mark InfoToolbar
- (void)fadeOutToolbarInfo:(NSTimer*)theTimer
{
	CGRect old=showSightseeings.frame;
	_dyAnimation*=1.25;
	showSightseeings.frame=CGRectMake(old.origin.x+_dyAnimation, old.origin.y, 
									  old.size.width, old.size.height);
	//printf("Fade in toolbar! %.0f\n", old.origin.y-_dyAnimation);	
	
	if(old.origin.x>kScreenWidth-10){
		[theTimer invalidate];
		showSightseeings.frame=CGRectMake(kScreenWidth, old.origin.y, 
										  old.size.width, old.size.height);
		showSightseeings.hidden=YES;
		
		//self.scrollView.userInteractionEnabled = YES;
	}	
	
	
}
- (void)fadeInToolbarInfo:(NSTimer*)theTimer
{
	CGRect old=showSightseeings.frame;
	_dyAnimation*=1.25;
	showSightseeings.frame=CGRectMake(old.origin.x-_dyAnimation, old.origin.y, 
								  old.size.width, old.size.height);
	//printf("Fade in toolbar! %.0f\n", old.origin.y-_dyAnimation);	
	
	if(old.origin.x<kScreenWidth-old.size.width-10){
		[theTimer invalidate];
		showSightseeings.frame=CGRectMake(kScreenWidth-old.size.width, old.origin.y, 
									  old.size.width, old.size.height);
		//self.scrollView.userInteractionEnabled = YES;
	}	
	
		
}

-(void) hideToolbarInfoWithAnimationAndInfo:(int)nInfo
{
	//self.scrollView.userInteractionEnabled = NO;
	_dyAnimation=0.5f;
	
	if(_bAreWeInScrollMode)
	{
		showSightseeings.hidden=YES;				
		//self.scrollView.userInteractionEnabled = YES;		
	}	
	else
	if(nInfo==0){
		[NSTimer scheduledTimerWithTimeInterval:kTimeAnimation target:self 
									   selector:@selector(fadeOutToolbarInfo:) userInfo:nil repeats:YES];	

	}		
}

-(void) showToolbarInfoWithAnimationAndInfo:(int)nInfo
{	
	//self.scrollView.userInteractionEnabled = NO;
	_dyAnimation=0.5f;	
	CGRect oldSight=showSightseeings.frame;
	// show our baby:
	showSightseeings.hidden=NO;
	showSightseeings.frame=CGRectMake(kScreenWidth, 
									  kScreenHeight-kTabBarHeight-oldSight.size.height,
								  oldSight.size.width, oldSight.size.height);
	
	if(_bAreWeInScrollMode)
	{
		showSightseeings.frame=CGRectMake(kScreenWidth-oldSight.size.width, 
										  kScreenHeight-kTabBarHeight-oldSight.size.height,
										  oldSight.size.width, oldSight.size.height);
	}
	else	
	if(nInfo==0){
		[NSTimer scheduledTimerWithTimeInterval:kTimeAnimation target:self 
									   selector:@selector(fadeInToolbarInfo:) userInfo:nil repeats:YES];	
	}
}

@end
